<?php

declare(strict_types=1);

/**
 * User：Abell
 * Date：2020/5/3
 */

namespace App\Controller\Abell;

use App\Controller\AbstractController;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Annotation\RequestMapping;
use Hyperf\Utils\Parallel;
use Hyperf\Utils\WaitGroup;
use Swoole\Coroutine;
use Hyperf\Di\Annotation\Inject;//引入@Inject注解
use Hyperf\HttpServer\Annotation\Controller;

/**
 * @Controller()
 */
class CoController extends AbstractController
{
    /**
     * @Inject()
     * @var \Hyperf\Guzzle\ClientFactory
     */
    private $clientFactory;

    /**
     *  批量复制协程数组执行代码
     * @RequestMapping(path="/abell/co/manypara", methods="get,post")
     */
    public function manypara(RequestInterface $request){

    }

    private $ae_host = 'http://192.168.2.104:9501/';
    /**
     *  创建协程的3种方式3 简洁版,返回值不带key
     * @RequestMapping(path="/abell/co/spal", methods="get,post")
     */
    public function spal(RequestInterface $request){
        return \parallel([
            function (){
                $client = $this->clientFactory->create();
                var_dump('1==');
                var_dump(date( "Y-m-d H:i",time()));
                $client->get($this->ae_host.'admin/abell/sleep?second=2');
                return 123;
            },
            function (){
                $client = $this->clientFactory->create();
                var_dump('2==');
                var_dump(date( "Y-m-d H:i",time()));
                $client->get($this->ae_host.'admin/abell/sleep?second=2');
                return 123;
            }
        ]);
        // 这里直接使用全局方法parallel 传入两个数组方法,返回值也必将简洁
    }

    /**
     *  创建协程的3种方式3
     * @RequestMapping(path="/abell/co/aepal", methods="get,post")
     */
    public function aepal(RequestInterface $request){
        $aepara = new Parallel();
        var_dump('0==');
        var_dump(date( "Y-m-d H:i",time()));
        // add一个协程
//        $aepara->add(function (){
//            $client = $this->clientFactory->create();
//            var_dump('1==');
//            var_dump(date( "Y-m-d H:i",time()));
//            $client->get($this->ae_host.'admin/abell/sleep?second=2');
//            return 123;
//        }); // 这里不加key,则默认用数字作为返回值key

        $aepara->add(function (){
            $client = $this->clientFactory->create();
            var_dump('1==');
            var_dump(date( "Y-m-d H:i",time()));
            $client->get($this->ae_host.'admin/abell/sleep?second=2');
            return 123;
        },'foo'); //这里加上返回值,则使用对应的key作为return返回

//        $aepara->add(function (){
//            $client = $this->clientFactory->create();
//            var_dump('2==');
//            var_dump(date( "Y-m-d H:i",time()));
//            $client->get($this->ae_host.'admin/abell/sleep?second=2');
//            return 321;
//        });
        $aepara->add(function (){
            $client = $this->clientFactory->create();
            var_dump('2==');
            var_dump(date( "Y-m-d H:i",time()));
            $client->get($this->ae_host.'admin/abell/sleep?second=2');
            return 321;
        },'bar');
        /*{
    "foo": 123,
    "bar": 321
}*/
        $result = $aepara->wait();
        var_dump('3==');
        var_dump(date( "Y-m-d H:i",time()));
        return $result;
    }

    /**
     *  创建协程的3种方式2 通过waitgroup来实现
     * @RequestMapping(path="/abell/co/aewait", methods="get,post")
     */
    public function aewait(RequestInterface $request){
        $aewg = new WaitGroup();
        $result = [];
        var_dump('1==');
        var_dump(date( "Y-m-d H:i",time()));
        $aewg->add(2);//建立多少个需要等待的线程
        Coroutine::create(function () use ($aewg,&$result){
            $client = $this->clientFactory->create();
            var_dump('2==');
            var_dump(date( "Y-m-d H:i",time()));
            $client->get($this->ae_host.'admin/abell/sleep?second=2');
            var_dump('3==');
            var_dump(date( "Y-m-d H:i",time()));
            $result[] = 123;
            $aewg->done(); // 这里表示执行完毕,会给对应的计数器减一
        });
        Coroutine::create(function () use ($aewg,&$result){
            $client = $this->clientFactory->create();
            var_dump('4==');
            var_dump(date( "Y-m-d H:i",time()));
            $client->get($this->ae_host.'admin/abell/sleep?second=2');
            var_dump('5==');
            var_dump(date( "Y-m-d H:i",time()));
            $result[] = 321;
            $aewg->done();
        });
        var_dump('6==');
        var_dump(date( "Y-m-d H:i",time()));
        /*waitgroup的实现方法
         * */
        $aewg->wait();
        return $result;
    }

    /**
     *  创建协程的3种方式1
     * @RequestMapping(path="/abell/co/abell", methods="get,post")
     */
    public function abell()
    {
        // 使用协程情况下执行两次
//        $channl = new Channel();
        $channl = new Coroutine\Channel();
        var_dump('1==');
        var_dump(date( "Y-m-d H:i",time()));
        Coroutine::create(function () use ($channl){
            $client = $this->clientFactory->create();
            var_dump('2==');
            var_dump(date( "Y-m-d H:i",time()));
            $client->get($this->ae_host.'admin/abell/sleep?second=2');
            var_dump('3==');
            var_dump(date( "Y-m-d H:i",time()));
            $channl->push(123);
        });
        Coroutine::create(function () use ($channl){
            $client = $this->clientFactory->create();
            var_dump('4==');
            var_dump(date( "Y-m-d H:i",time()));
            $client->get($this->ae_host.'admin/abell/sleep?second=2');
            var_dump('5==');
            var_dump(date( "Y-m-d H:i",time()));
            $channl->push(321);
        });
        var_dump('6==');
        var_dump(date( "Y-m-d H:i",time()));
        $result[] = $channl->pop(); //取得第一个协程的值
        var_dump('7==');
        var_dump(date( "Y-m-d H:i",time()));
        $result[] = $channl->pop(); // 取得第二个协程的值
        var_dump('8==');
        var_dump(date( "Y-m-d H:i",time()));
        /*这样经过2秒就完成了上面不使用协程4秒才能完成的方法
        执行过程是 1-2-4-6-5-3 在2-3的时候遇到阻塞就执行下面的4,又遇到阻塞就执行6,然后在阻塞完成后再执行5和3
         * */
        return $result;
    }

    public function sleep(RequestInterface $request){
        $second = $request->query('seconds',1);
        sleep($second);
        return $second;
    }

    /**
     *  创建协程的3种方式2
     * @RequestMapping(path="/abell/co/test", methods="get,post")
     */
    public function test(RequestInterface $request){
        // 不使用协程的情况 请求2次 这样的请求就是同步的,会造成阻塞
        $client = $this->clientFactory->create();
        $client->get($this->ae_host.'admin/abell/sleep?second=2');
        $client = $this->clientFactory->create();
        $client->get($this->ae_host.'admin/abell/sleep?second=2');
        return 'hello';
    }



}
